﻿// <copyright file="TrackSmoothStreamingMediaElement.cs" company="Microsoft Corporation">
// Copyright (c) 2009 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-09-03</date>
// <summary>TrackSmoothStreamingMediaElement class definition</summary>

namespace Microsoft.WebAnalytics.Media
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Windows;
    using System.Windows.Interactivity;
    using System.Windows.Media;
    using Microsoft.Web.Media.SmoothStreaming;
    using Microsoft.WebAnalytics;
    using Microsoft.WebAnalytics.Data;

    /// <summary>
    /// <img src="../media/Microsoft.WebAnalytics.Media.TrackSmoothStreamingMediaElement.24x24.png"/> 
    /// Smooth Streaming Client event tracking
    /// </summary>
    /// <remarks>
    /// Platforms: Silverlight 4, Windows Phone 7
    /// This tracks events from the <see cref="Microsoft.Web.Media.SmoothStreaming.SmoothStreamingMediaElement"/> which is 
    /// part of the <a href="http://www.iis.net/download/SmoothClient">Smooth 
    /// Streaming Client</a> and references the Microsoft.Web.MediaSmoothStreaming.dll assembly.
    /// <list type="table">
    /// <listheader>
    /// <term>Event Name</term>
    /// <description>Description</description>
    /// </listheader>
    /// <item>
    /// <term>BufferingProgressChanged</term>
    /// <description>Event that occurs when the BufferingProgress property changes.</description>
    /// </item>
    /// <item>
    /// <term>ClipClickThrough</term>
    /// <description>Event that occurs when a user clicks the media display.</description>
    /// </item>
    /// <item>
    /// <term>ClipError</term>
    /// <description>Event when an error occurs during play of audio or video media.</description>
    /// </item>
    /// <item>
    /// <term>ClipProgressUpdate</term>
    /// <description>Event that occurs when media hits a marker.</description>
    /// </item>
    /// <item>
    /// <term>ClipStateChanged</term>
    /// <description>Event that occurs when a media clip state changes.</description>
    /// </item>
    /// <item>
    /// <term>CurrentStateChanged</term>
    /// <description>Event that occurs when the current state of media element changes.</description>
    /// </item>
    /// <item>
    /// <term>DownloadProgressChanged</term>
    /// <description>Event that occurs when the DownloadProgress property changes.</description>
    /// </item>
    /// <item>
    /// <term>DownloadTrackChanged</term>
    /// <description>Event that occurs when the track selected for download differs from the previously selected track.</description>
    /// </item>
    /// <item>
    /// <term>LiveEventCompleted</term>
    /// <description>Event that occurs when a live media stream ends.</description>
    /// </item>
    /// <item>
    /// <term>LogReady</term>
    /// <description>Event that occurs when the log generated by the RequestLog method is ready.</description>
    /// </item>
    /// <item>
    /// <term>ManifestReady</term>
    /// <description>Event that occurs when the manifest for the Smooth Streaming content is available for track selection.</description>
    /// </item>
    /// <item>
    /// <term>MarkerReached</term>
    /// <description>Event that occurs when media playback hits a timeline marker.</description>
    /// </item>
    /// <item>
    /// <term>MediaEnded</term>
    /// <description>Event that occurs when media playback reaches the end.</description>
    /// </item>
    /// <item>
    /// <term>MediaFailed</term>
    /// <description>Event that occurs when there is an error associated with the media source.</description>
    /// </item>
    /// <item>
    /// <term>MediaOpened</term>
    /// <description>Event that occurs when the media stream has been validated and opened and the file headers have been read.</description>
    /// </item>
    /// <item>
    /// <term>PlaybackTrackChanged</term>
    /// <description>Event that occurs when the currently playing track changes.</description>
    /// </item>
    /// <item>
    /// <term>SeekCompleted</term>
    /// <description>Event that occurs when a seek operation completes.</description>
    /// </item>
    /// <item>
    /// <term>SmoothStreamingErrorOccurred</term>
    /// <description>Event invoked when an error occurs during playback of Smooth Streaming content.</description>
    /// </item>
    /// <item>
    /// <term>VideoHighestPlayableTrackChanged</term>
    /// <description>Event activated on playback rate change to highest available rate.</description>
    /// </item>
    /// </list>
    /// </remarks>
    /// <example>
    /// Adding this behavior via code:
    /// <code>
    /// var ssme = new SmoothStreamingMediaElement();
    /// var behaviors = System.Windows.Interactivity.Interaction.GetBehaviors(ssme);
    /// behaviors.Add(new TrackSmoothStreamingMediaElement());
    /// </code>
    /// </example>
    public class TrackSmoothStreamingMediaElement : Behavior<SmoothStreamingMediaElement>
    {
        /// <summary>
        /// Initializes a new instance of the TrackSmoothStreamingMediaElement class
        /// </summary>
        public TrackSmoothStreamingMediaElement()
        {
            this.CustomProperties = new Collection<PropertyValue>();
        }

        #region Properties
        /// <summary>
        /// Gets custom properties (name/value pairs) for the action
        /// </summary>
        public Collection<PropertyValue> CustomProperties { get; private set; }

        /// <summary>
        /// Gets or sets the event Logging method
        /// </summary>
        [Import("Log")]
        public Action<AnalyticsEvent> Log { get; set; }

        /// <summary>
        /// Gets the Media Source or Smooth Streaming Source
        /// </summary>
        private Uri Source
        {
            get
            {
                if (this.AssociatedObject.SmoothStreamingSource == null)
                {
                    return this.AssociatedObject.Source;
                }

                return this.AssociatedObject.SmoothStreamingSource;
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Initialize the imports and attach the event handlers
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            CompositionInitializerEx.SatisfyImports(this);

#if WINDOWS_PHONE
#else
            this.AssociatedObject.ClipClickThrough += new EventHandler<ClipEventArgs>(this.ClipClickThrough);
            this.AssociatedObject.ClipError += new EventHandler<ClipEventArgs>(this.ClipError);
            this.AssociatedObject.ClipProgressUpdate += new EventHandler<ClipPlaybackEventArgs>(this.AssociatedObject_ClipProgressUpdate);
            this.AssociatedObject.ClipStateChanged += new EventHandler<ClipEventArgs>(this.ClipStateChanged);
            this.AssociatedObject.MarkerReached += new TimelineMarkerRoutedEventHandler(this.MarkerReached);
#endif
            this.AssociatedObject.BufferingProgressChanged += new RoutedEventHandler(this.BufferingProgressChanged);
            this.AssociatedObject.CurrentStateChanged += new RoutedEventHandler(this.CurrentStateChanged);
            this.AssociatedObject.DownloadProgressChanged += new RoutedEventHandler(this.AssociatedObject_DownloadProgressChanged);
            this.AssociatedObject.DownloadTrackChanged += new EventHandler<TrackChangedEventArgs>(this.DownloadTrackChanged);
            this.AssociatedObject.LiveEventCompleted += new EventHandler(this.LiveEventCompleted);
            this.AssociatedObject.LogReady += new SSMELogReadyRoutedEventHandler(this.LogReady);
            this.AssociatedObject.ManifestReady += new EventHandler<EventArgs>(this.AssociatedObject_ManifestReady);
            this.AssociatedObject.MediaEnded += new RoutedEventHandler(this.MediaEnded);
            this.AssociatedObject.MediaFailed += new EventHandler<ExceptionRoutedEventArgs>(this.MediaFailed);
            this.AssociatedObject.MediaOpened += new RoutedEventHandler(this.MediaOpened);
            this.AssociatedObject.PlaybackTrackChanged += new EventHandler<TrackChangedEventArgs>(this.PlaybackTrackChanged);
            this.AssociatedObject.SeekCompleted += new EventHandler<SeekCompletedEventArgs>(this.SeekCompleted);
            this.AssociatedObject.SmoothStreamingErrorOccurred += new EventHandler<SmoothStreamingErrorEventArgs>(this.SmoothStreamingErrorOccurred);
            this.AssociatedObject.VideoHighestPlayableTrackChanged += new EventHandler<TrackChangedEventArgs>(this.AssociatedObject_VideoHighestPlayableTrackChanged);

            this.AssociatedObject.Unloaded += new RoutedEventHandler(delegate(object sender, RoutedEventArgs args)
            {
                System.Windows.Interactivity.Interaction.GetBehaviors(this.AssociatedObject).Remove(this);
            });
        }

        /// <summary>
        /// Detach the event handlers
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();
#if WINDOWS_PHONE
#else
            this.AssociatedObject.ClipClickThrough -= new EventHandler<ClipEventArgs>(this.ClipClickThrough);
            this.AssociatedObject.ClipError -= new EventHandler<ClipEventArgs>(this.ClipError);
            this.AssociatedObject.ClipProgressUpdate -= new EventHandler<ClipPlaybackEventArgs>(this.AssociatedObject_ClipProgressUpdate);
            this.AssociatedObject.ClipStateChanged -= new EventHandler<ClipEventArgs>(this.ClipStateChanged);
            this.AssociatedObject.MarkerReached -= new TimelineMarkerRoutedEventHandler(this.MarkerReached);
#endif
            this.AssociatedObject.BufferingProgressChanged -= new RoutedEventHandler(this.BufferingProgressChanged);
            this.AssociatedObject.CurrentStateChanged -= new RoutedEventHandler(this.CurrentStateChanged);
            this.AssociatedObject.DownloadProgressChanged -= new RoutedEventHandler(this.AssociatedObject_DownloadProgressChanged);
            this.AssociatedObject.DownloadTrackChanged -= new EventHandler<TrackChangedEventArgs>(this.DownloadTrackChanged);
            this.AssociatedObject.LiveEventCompleted -= new EventHandler(this.LiveEventCompleted);
            this.AssociatedObject.LogReady -= new SSMELogReadyRoutedEventHandler(this.LogReady);
            this.AssociatedObject.ManifestReady -= new EventHandler<EventArgs>(this.AssociatedObject_ManifestReady);
            this.AssociatedObject.MediaEnded -= new RoutedEventHandler(this.MediaEnded);
            this.AssociatedObject.MediaFailed -= new EventHandler<ExceptionRoutedEventArgs>(this.MediaFailed);
            this.AssociatedObject.MediaOpened -= new RoutedEventHandler(this.MediaOpened);
            this.AssociatedObject.PlaybackTrackChanged -= new EventHandler<TrackChangedEventArgs>(this.PlaybackTrackChanged);
            this.AssociatedObject.SeekCompleted -= new EventHandler<SeekCompletedEventArgs>(this.SeekCompleted);
            this.AssociatedObject.SmoothStreamingErrorOccurred -= new EventHandler<SmoothStreamingErrorEventArgs>(this.SmoothStreamingErrorOccurred);
            this.AssociatedObject.VideoHighestPlayableTrackChanged -= new EventHandler<TrackChangedEventArgs>(this.AssociatedObject_VideoHighestPlayableTrackChanged);
        }

        #endregion

        #region Implementation

        /// <summary>
        /// Log a TimelineEventReached event
        /// </summary>
        /// <param name="sender">the SSME object</param>
        /// <param name="e">the timeline event arguments</param>
        ////private void TimelineEventReached(object sender, TimelineEventArgs e)
        ////{
        ////    var logEvent = new AnalyticsEvent()
        ////    {
        ////        EventArgs = this.CustomProperties,
        ////        Name = "TimelineEventReached",
        ////        ObjectName = this.AssociatedObject.Name,
        ////        ObjectType = this.AssociatedObject.GetType().Name,
        ////        MediaSource = this.Source,
        ////        MediaTimeCode = this.AssociatedObject.Position,
        ////        Track = new Microsoft.WebAnalytics.Data.TrackInfo()
        ////        {
        ////            Bitrate = System.Convert.ToInt64(e.Track.Bitrate),
        ////            CustomAttributes = new Dictionary<string, string>(e.Track.CustomAttributes),
        ////            Index = e.Track.Index,
        ////            Language = e.Track.Language,
        ////            Name = e.Track.Name,
        ////            TrackData = new List<Microsoft.WebAnalytics.Data.TimelineEvent>(from timelineEvent in e.Track.TrackData
        ////                                                                            select new Microsoft.WebAnalytics.Data.TimelineEvent
        ////                                                                            {
        ////                                                                                EventTime = timelineEvent.EventTime
        ////                                                                            }),
        ////        },
        ////        Value = System.Convert.ToInt32(e.IsCurrent),   
        ////    };

        ////    this.Log(logEvent);
        ////}

        private void AssociatedObject_VideoHighestPlayableTrackChanged(object sender, TrackChangedEventArgs e)
        {
            var eventArg = new Collection<PropertyValue>(this.CustomProperties);

            foreach (var item in e.NewTrack.Attributes)
            {
                eventArg.Add(new PropertyValue { PropertyName = item.Key, Value = item.Value });
            }

            foreach (var item in e.NewTrack.Stream.Attributes)
            {
                eventArg.Add(new PropertyValue { PropertyName = item.Key, Value = item.Value });
            }

            var logEvent = new AnalyticsEvent()
            {
                EventArgs = eventArg,
                Name = "VideoHighestPlayableTrackChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
                Track = new Microsoft.WebAnalytics.Data.TrackInfo()
                {
                    Bitrate = System.Convert.ToInt64(e.NewTrack.Bitrate),
                    CustomAttributes = new Dictionary<string, string>(e.NewTrack.CustomAttributes),
                    Index = e.NewTrack.Index,

                    ////Language = e.NewTrack.Language,
                    ////Name = e.NewTrack.Name,
                    ////TrackData = new List<Microsoft.WebAnalytics.Data.TimelineEvent>(from timelineEvent in e.NewTrack.Attributes
                    ////                                                                select new Microsoft.WebAnalytics.Data.TimelineEvent
                    ////                                                                {
                    ////                                                                    EventTime = timelineEvent.EventTime
                    ////                                                                }),
                },
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Track the ManifestReady event
        /// </summary>
        /// <param name="sender">the Smooth Streaming Media Element</param>
        /// <param name="e">the event arguments</param>
        private void AssociatedObject_ManifestReady(object sender, EventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "ManifestReady",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Track the DownloadProgressChanged event
        /// </summary>
        /// <param name="sender">the smooth streaming media element</param>
        /// <param name="e">the routed event arguments</param>
        private void AssociatedObject_DownloadProgressChanged(object sender, RoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "DownloadProgressChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
                Value = System.Convert.ToInt32(this.AssociatedObject.DownloadProgress * 100)
            };

            this.Log(logEvent);
        }

#if WINDOWS_PHONE
#else
        /// <summary>
        /// Track the ClipProgressUpdate event
        /// </summary>
        /// <param name="sender">the Smooth Streaming Media Element</param>
        /// <param name="e">the clip playback event arguments</param>
        private void AssociatedObject_ClipProgressUpdate(object sender, ClipPlaybackEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "ClipProgressUpdate",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }
#endif
        /// <summary>
        /// Log a SmoothStreamingErrorOccurred event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the smooth streaming error event argumetns</param>
        private void SmoothStreamingErrorOccurred(object sender, SmoothStreamingErrorEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                ActionValue = e.ErrorMessage,
                EventArgs = this.CustomProperties,
                Name = "SmoothStreamingErrorOccurred",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
                Value = e.ErrorCode
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the SeekCompleted event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the seek completed event arguments</param>
        private void SeekCompleted(object sender, SeekCompletedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "SeekCompleted",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = e.ActualSeekPosition,
                Value = System.Convert.ToInt32(e.Success),   
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the PlaybackTrackChanged event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the track changed event arguments</param>
        private void PlaybackTrackChanged(object sender, TrackChangedEventArgs e)
        {
            var eventArg = new Collection<PropertyValue>(this.CustomProperties);

            foreach (var item in e.NewTrack.Attributes)
            {
                eventArg.Add(new PropertyValue { PropertyName = item.Key, Value = item.Value });
            }

            foreach (var item in e.NewTrack.Stream.Attributes)
            {
                eventArg.Add(new PropertyValue { PropertyName = item.Key, Value = item.Value });
            }

            var logEvent = new AnalyticsEvent()
            {
                EventArgs = eventArg,
                Name = "PlaybackTrackChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
                Track = new Microsoft.WebAnalytics.Data.TrackInfo()
                {
                    Bitrate = System.Convert.ToInt64(e.NewTrack.Bitrate),
                    CustomAttributes = new Dictionary<string, string>(e.NewTrack.CustomAttributes),
                    Index = e.NewTrack.Index,
                },
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the MediaOpened Event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the routed event arguments</param>
        private void MediaOpened(object sender, RoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "MediaOpened",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the MediaFailed event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the exception routed event arguments</param>
        private void MediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                ActionValue = e.ErrorException.Message,
                EventArgs = this.CustomProperties,
                Name = "MediaFailed",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the MediaEnded event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the routed event arguments</param>
        private void MediaEnded(object sender, RoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "MediaEnded",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the MarkerReached event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the timeline marker routed event arguments</param>
        private void MarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                ActionValue = e.Marker.Text,
                EventArgs = this.CustomProperties,
                Name = "MarkerReached",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the LogReady event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the log ready routed event arguments</param>
        private void LogReady(object sender, SSMELogReadyRoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                ActionValue = e.Log,
                EventArgs = this.CustomProperties,
                Name = "LogReady",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the LiveEventCompleted event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the event arguments</param>
        private void LiveEventCompleted(object sender, EventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "LiveEventCompleted",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the DownloadTrackChanged event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the track changed event arguments</param>
        private void DownloadTrackChanged(object sender, TrackChangedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                ActionValue = this.AssociatedObject.CurrentState.ToString(),
                EventArgs = this.CustomProperties,
                Name = "DownloadTrackChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaStreamType = e.StreamType,
                MediaTimeCode = this.AssociatedObject.Position,
                Track = new Microsoft.WebAnalytics.Data.TrackInfo()
                {
                    Bitrate = System.Convert.ToInt64(e.NewTrack.Bitrate),
                    CustomAttributes = new Dictionary<string, string>(e.NewTrack.CustomAttributes),
                    Index = e.NewTrack.Index,
                },
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the CurrentStateChanged event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the routed event arguments</param>
        private void CurrentStateChanged(object sender, RoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                ActionValue = this.AssociatedObject.CurrentState.ToString(),
                EventArgs = this.CustomProperties,
                Name = "CurrentStateChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

#if WINDOWS_PHONE
#else
        /// <summary>
        /// Log the ClipStateChanged event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the routed event arguments</param>
        private void ClipStateChanged(object sender, ClipEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Name = "ClipStateChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the ClipError event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the clip event arguments</param>
        private void ClipError(object sender, ClipEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Clip = new Microsoft.WebAnalytics.Data.ClipContext()
                {
                    ClipInformation = new Microsoft.WebAnalytics.Data.ClipInformation()
                    {
                        ClickThroughUrl = e.Context.ClipInformation.ClickThroughUri,
                        ClipUrl = e.Context.ClipInformation.ClipUri,
                        Duration = e.Context.ClipInformation.Duration,
                        IsSmoothStreamingSource = e.Context.ClipInformation.IsSmoothStreamingSource
                    },
                    Data = e.Context.Data,
                    CurrentClipState = e.Context.CurrentClipState,
                    HasQuartileEvents = e.Context.HasQuartileEvents,
                },
                Name = "ClipError",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
            };

            this.Log(logEvent);
        }

        /// <summary>
        /// Log the ClipClickThrough event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the clip event arguments</param>
        private void ClipClickThrough(object sender, ClipEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                EventArgs = this.CustomProperties,
                Clip = new Microsoft.WebAnalytics.Data.ClipContext()
                {
                    ClipInformation = new Microsoft.WebAnalytics.Data.ClipInformation()
                    {
                        ClickThroughUrl = e.Context.ClipInformation.ClickThroughUri,
                        ClipUrl = e.Context.ClipInformation.ClipUri,
                        Duration = e.Context.ClipInformation.Duration,
                        IsSmoothStreamingSource = e.Context.ClipInformation.IsSmoothStreamingSource
                    },
                    Data = e.Context.Data,
                    CurrentClipState = e.Context.CurrentClipState,
                    HasQuartileEvents = e.Context.HasQuartileEvents,
                },
                MediaTimeCode = this.AssociatedObject.Position,
                Name = "ClipClickThrough",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
            };

            this.Log(logEvent);
        }
#endif
        /// <summary>
        /// Log the BufferingProgressChanged event
        /// </summary>
        /// <param name="sender">the SmoothStreamingMediaElement</param>
        /// <param name="e">the routed event arguments</param>
        private void BufferingProgressChanged(object sender, RoutedEventArgs e)
        {
            var logEvent = new AnalyticsEvent()
            {
                Name = "BufferingProgressChanged",
                ObjectName = this.AssociatedObject.Name,
                ObjectType = this.AssociatedObject.GetType().Name,
                MediaSource = this.Source,
                MediaTimeCode = this.AssociatedObject.Position,
                Value = System.Convert.ToInt32(this.AssociatedObject.BufferingProgress * 100)
            };

            this.Log(logEvent);
        }

        #endregion
    }
}
